import tkinter as tk
# 使用对话框
from tkinter import simpledialog,messagebox
from PIL import Image, ImageDraw, ImageFont,ImageTk

# windows 字体库
win = {"宋体":"C:/Windows/Fonts/simsun.ttc",
       "黑体":"C:/Windows/Fonts/simhei.ttf",
       "隶书":"C:/Windows/Fonts/SIMLI.TTF"}
# 汉字特征库
mode = {}
# 开始统计
def go():
    global win,mode
    size = int(size_var.get())
    font = font_var.get()
    cn = cn_text.get().split()

    for k in cn:
        # 汉字生成图片，RGBA模式有透明度，白色背景
        cs = Image.new('RGBA', (size, size), (255, 255, 255, 0))
        draw = ImageDraw.Draw(cs)
        font_path = win[font]
        font_str = ImageFont.truetype(font_path, size)
        # 黑色字
        draw.text((0, 0), k,fill=(0, 0, 0, 255), font=font_str)
        # 转换为 Tkinter 图像
        photo = ImageTk.PhotoImage(cs)

        # 在 Tkinter 中显示图像
        label = tk.Label(imgs_frame, image=photo)
        # 防止图像被垃圾回收，否则图片不显示
        label.image = photo
        label.pack(side='left')

        # 核心部分：获得图片信息
        data = list(cs.getdata())
        point = {}  # 像素位
        # 逐行
        for i in range(size):
            # 逐列
            for j in range(size):
                id = f"{i}_{j}"
                s = i * size + j
                # 这里使用透明度即可
                if data[s][3] > 0:
                    # 如果有值就记为 1
                    point[id] = 1
                else:
                    # 否则记为 0
                    point[id] = 0

        # 追加到特征库中：汉字=特征
        mode[k] = point
    # 显示数据模型，方便观察
    print(mode)
    # 开始验证
    test()

# 开始测试
def test():
    global win,mode
    # 返回用户输入的汉字
    test_str = simpledialog.askstring('输入汉字', '请输入一个汉字用于测试！')
    if not test_str:
        return

    # 核心代码：重复汉字生成图片中单个汉字的特征提取过程。
    # 像素大小
    size = int(size_var.get())
    # 字体类型
    font = font_var.get()

    # 汉字生成图片, 切记要保证与 go() 函数中的图片生成过程一致，实在不行就只复制过来。
    cs = Image.new('RGBA', (size, size), (255, 255, 255, 0))
    draw = ImageDraw.Draw(cs)
    font_path = win[font]
    font_str = ImageFont.truetype(font_path, size)
    draw.text((0, 0), test_str,fill=(0, 0, 0, 255), font=font_str)
    # 转换为 Tkinter 图像
    photo = ImageTk.PhotoImage(cs)
    label = tk.Label(imgs_frame, image=photo)
    # 防止图像被垃圾回收，否则图片不显示
    label.image = photo
    label.pack(side='left')

    # 获得当前文字的特征集合
    data = list(cs.getdata())
    point = {}
    # 逐行
    for i in range(size):
        # 逐列
        for j in range(size):
            id = f"{i}_{j}"
            s = i * size + j
            if data[s][3] > 0:
                point[id] = 1
            else:
                point[id] = 0

    # 算法核心：与特征库中的所有特征进行匹配，然后计算命中率。
    word = ''  # 对应的字符
    max_val = 0  # 最大值
    for key in mode:
        ps = mode[key]
        sum = 0  # 特征总数
        num = 0  # 总命中数
        for p in ps:
            # 可以只比对比特征位
            if ps[p] == 1:
                sum += 1  # 累计特征总数
                if ps[p] == point[p]:
                    # 累计命中数
                    num += 1

        # 命中率：命中数÷当前特位总数
        ps_i = num / sum
        # 返回最大命中率和它对应的汉字
        if ps_i > max_val:
            max_val = ps_i
            word = key

    messagebox.showinfo('识别结果', f'你输入的这个字很可能是：{word}')


# 创建主窗口
root = tk.Tk()
root.title('通过像素对比识别汉字')
size_var = tk.StringVar()
size_var.set("16")
font_var = tk.StringVar()
font_var.set("黑体")
# 输入框
cn_text = tk.Entry(root)
cn_text.insert(0,'人 口 手 金 木 水 火 土 阴 阳')
cn_text.pack()

# 按钮
frame = tk.Frame(root)
frame.pack(pady=10)
tk.Button(frame, text='测试', command=test).pack(side='left')
# 像素大小输入框
tk.Label(frame, text='像素大小：').pack(side='left')
tk.Entry(frame,textvariable=size_var).pack(side='left')
# 字体选择
tk.Label(frame, text='字体：').pack(side='left')
font_menu = tk.OptionMenu(frame, font_var, '宋体', '黑体', '隶书')
font_menu.pack(side='left')
tk.Button(frame, text='开始', command=go).pack(side='left')


# 图片显示区域
imgs_frame = tk.Frame(root)
imgs_frame.pack(pady=10)

# 运行主循环
root.mainloop()